home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Games / NetHack 3.1.3 / source / util / recover.c < prev   
Encoding:
C/C++ Source or Header  |  1993-08-01  |  5.6 KB  |  288 lines  |  [TEXT/R*ch]

  1. /*    SCCS Id: @(#)recover.c    3.1    93/05/15    */
  2. /*    Copyright (c) Janet Walz, 1992.                  */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. /*
  6.  *  Utility for reconstructing NetHack save file from a set of individual
  7.  *  level files.  Requires that the `checkpoint' option be enabled at the
  8.  *  time NetHack creates those level files.
  9.  */
  10. #include "config.h"
  11. #if !defined(O_WRONLY) && !defined(LSC) && !defined(AZTEC_C)
  12. #include <fcntl.h>
  13. #endif
  14.  
  15. #ifndef VMS
  16. # ifdef exit
  17. #  undef exit
  18. # endif
  19. #ifdef MICRO
  20. extern void FDECL(exit, (int));
  21. #endif
  22. #else    /* VMS */
  23. extern int FDECL(vms_creat, (const char *,unsigned));
  24. extern int FDECL(vms_open, (const char *,int,unsigned));
  25. #endif    /* VMS */
  26.  
  27. int FDECL(restore_savefile, (char *));
  28. void FDECL(set_levelfile_name, (int));
  29. int FDECL(open_levelfile, (int));
  30. int NDECL(create_savefile);
  31. void FDECL(copy_bytes, (int,int));
  32.  
  33. #ifdef UNIX
  34. #define SAVESIZE    (PL_NSIZ + 13)    /* save/99999player.e */
  35. #else
  36. # ifdef VMS
  37. #define SAVESIZE    (PL_NSIZ + 22)    /* [.save]<uid>player.e;1 */
  38. # else
  39. #define SAVESIZE    FILENAME    /* from macconf.h or pcconf.h */
  40. # endif
  41. #endif
  42.  
  43. char savename[SAVESIZE]; /* holds relative path of save file from playground */
  44.  
  45.  
  46. int
  47. main(argc, argv)
  48. int argc;
  49. char *argv[];
  50. {
  51.     int argno;
  52.     const char *dir = (char *)0;
  53. #ifdef AMIGA
  54.     char *startdir = (char *)0;
  55. #endif
  56.  
  57.     if (argc == 1 || (argc == 2 && !strcmp(argv[1], "-"))) {
  58.         (void) fprintf(stderr,
  59.                 "Usage: %s [-d directory] base1 base2 ...\n",
  60.                 argv[0]);
  61.         exit(1);
  62.     }
  63.  
  64.     argno = 1;
  65.     if (!strncmp(argv[argno], "-d", 2)) {
  66.         dir = argv[argno]+2;
  67.         if (*dir == '=' || *dir == ':') dir++;
  68.         if (!*dir && argc > argno) {
  69.             argno++;
  70.             dir = argv[argno];
  71.         }
  72.         if (!*dir) {
  73.             (void) fprintf(stderr,
  74.             "%s: flag -d must be followed by a directory name.\n",
  75.             argv[0]);
  76.             exit(1);
  77.         }
  78.         argno++;
  79.     }
  80.  
  81.     if (!dir) dir = getenv("NETHACKDIR");
  82.     if (!dir) dir = getenv("HACKDIR");
  83. #if defined(SECURE) && !defined(VMS)
  84.     if (dir
  85. # ifdef HACKDIR
  86.         && strcmp(dir, HACKDIR)
  87. # endif
  88.         ) {
  89.         (void) setgid(getgid());
  90.         (void) setuid(getuid());
  91.     }
  92. #endif    /* SECURE && !VMS */
  93.  
  94. #ifdef HACKDIR
  95.     if (!dir) dir = HACKDIR;
  96. #endif
  97.  
  98. #ifdef AMIGA
  99.     startdir = getcwd(0,255);
  100. #endif
  101.     if (dir && chdir((char *) dir) < 0) {
  102.         (void) fprintf(stderr, "%s: cannot chdir to %s.\n",
  103.                 argv[0], dir);
  104.         exit(1);
  105.     }
  106.  
  107.     while (argc > argno) {
  108.         (void) restore_savefile(argv[argno]);
  109.         argno++;
  110.     }
  111. #ifdef AMIGA
  112.     if (startdir) (void)chdir(startdir);
  113. #endif
  114. #ifndef VMS
  115.     return 0;
  116. #else
  117.     return 1;       /* vms success */
  118. #endif /*VMS*/
  119. }
  120.  
  121. static char lock[256];
  122.  
  123. void
  124. set_levelfile_name(lev)
  125. int lev;
  126. {
  127.     char *tf;
  128.  
  129.     tf = rindex(lock, '.');
  130.     if (!tf) {
  131.         tf = lock;
  132.         while (*tf) tf++;
  133.     }
  134. #ifdef VMS
  135.     (void) sprintf(tf, ".%d;1", lev);
  136. #else
  137.     (void) sprintf(tf, ".%d", lev);
  138. #endif
  139. }
  140.  
  141. int
  142. open_levelfile(lev)
  143. int lev;
  144. {
  145.     int fd;
  146.  
  147.     set_levelfile_name(lev);
  148. #ifdef MICRO
  149.     fd = open(lock, O_RDONLY | O_BINARY);
  150. #else
  151.     fd = open(lock, O_RDONLY, 0);
  152. #endif
  153.     return fd;
  154. }
  155.  
  156. int
  157. create_savefile()
  158. {
  159.     int fd;
  160.  
  161. #ifdef MICRO
  162.     fd = open(savename, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, FCMASK);
  163. #else
  164.     fd = creat(savename, FCMASK);
  165. #endif
  166.     return fd;
  167. }
  168.  
  169. void
  170. copy_bytes(ifd, ofd)
  171. int ifd, ofd;
  172. {
  173.     char buf[BUFSIZ];
  174.     int nfrom, nto;
  175.  
  176.     do {
  177.         nfrom = read(ifd, buf, BUFSIZ);
  178.         nto = write(ofd, buf, nfrom);
  179.         if (nto != nfrom) {
  180.             (void) fprintf(stderr, "file copy failed!\n");
  181.             exit(1);
  182.         }
  183.     } while (nfrom == BUFSIZ);
  184. }
  185.  
  186. int
  187. restore_savefile(basename)
  188. char *basename;
  189. {
  190.     int gfd, lfd, sfd;
  191.     int lev, savelev, hpid;
  192.     xchar levc;
  193.  
  194.     /* level 0 file contains:
  195.      *    pid of creating process (ignored here)
  196.      *    level number for current level of save file
  197.      *    name of save file nethack would have created
  198.      *    and game state
  199.      */
  200.     (void) strcpy(lock, basename);
  201.     gfd = open_levelfile(0);
  202.     if (gfd < 0) {
  203.         (void) fprintf(stderr, "Cannot open level 0 for %s.\n", basename);
  204.         return(-1);
  205.     }
  206.     (void) read(gfd, (genericptr_t) &hpid, sizeof(hpid));
  207.     if (read(gfd, (genericptr_t) &savelev, sizeof(savelev))
  208.                             != sizeof(savelev)) {
  209.         (void) fprintf(stderr,
  210.         "Checkpointing was not in effect for %s -- recovery impossible.\n",
  211.         basename);
  212.         (void) close(gfd);
  213.         return(-1);
  214.     }
  215.     (void) read(gfd, (genericptr_t) savename, sizeof(savename));
  216.  
  217.     /* save file should contain:
  218.      *    current level (including pets)
  219.      *    (non-level-based) game state
  220.      *    other levels
  221.      */
  222.     sfd = create_savefile();
  223.     if (sfd < 0) {
  224.         (void) fprintf(stderr, "Cannot create savefile %s.\n", savename);
  225.         (void) close(gfd);
  226.         return(-1);
  227.     }
  228.  
  229.     lfd = open_levelfile(savelev);
  230.     if (lfd < 0) {
  231.         (void) fprintf(stderr, "Cannot open level of save for %s.\n",
  232.                 basename);
  233.         (void) close(gfd);
  234.         (void) close(sfd);
  235.         return(-1);
  236.     }
  237.  
  238.     copy_bytes(lfd, sfd);
  239.     (void) close(lfd);
  240.     (void) unlink(lock);
  241.  
  242.     copy_bytes(gfd, sfd);
  243.     (void) close(gfd);
  244.     set_levelfile_name(0);
  245.     (void) unlink(lock);
  246.  
  247.     for (lev = 1; lev < 256; lev++) {
  248.         /* level numbers are kept in xchars in save.c, so the
  249.          * maximum level number (for the endlevel) must be < 256
  250.          */
  251.         if (lev != savelev) {
  252.             lfd = open_levelfile(lev);
  253.             if (lfd >= 0) {
  254.                 /* any or all of these may not exist */
  255.                 levc = (xchar) lev;
  256.                 write(sfd, (genericptr_t) &levc, sizeof(levc));
  257.                 copy_bytes(lfd, sfd);
  258.                 (void) close(lfd);
  259.                 (void) unlink(lock);
  260.             }
  261.         }
  262.     }
  263.  
  264.     (void) close(sfd);
  265.  
  266. #ifdef AMIGA
  267.             /* we need to create an icon for the saved game
  268.              * or HackWB won't notice the file.
  269.              */
  270.     {
  271.     char iconfile[FILENAME];
  272.     int in, out;
  273.  
  274.     sprintf(iconfile,"%s.info",savename);
  275.     in=open("NetHack:default.icon",O_RDONLY);
  276.     out=open(iconfile,O_WRONLY | O_TRUNC | O_CREAT);
  277.     if(in > -1 && out > -1){
  278.         copy_bytes(in,out);
  279.     }
  280.     if(in > -1)close(in);
  281.     if(out > -1)close(out);
  282.     }
  283. #endif
  284.     return(0);
  285. }
  286.  
  287. /*recover.c*/
  288.